#include "nfc.h"
#include "iso14443b.h"

unsigned char PassWd[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
unsigned char RWDATA[16];

unsigned char IDB[10]; //放置B 卡ID
unsigned char IDA[10]; //放置A 卡ID
unsigned char CT[2];   //卡类型
/* 调试打印接口 */
#define NFC_TASK_LOG(format, ...) //  TASK_LOG(format, ##__VA_ARGS__)

static void nfc_delay_us(uint32_t us)
{
	Device_DelayUs(us);
}

static void nfc_delay_ms(uint32_t ms)
{
	Device_DelayMs(ms);
}


/////////////////////////////////////////////////////////////////////
//功    能：验证通讯是否成功
//参数说明：cnt[IN]:读寄存器次数
//返    回：成功返回MI_OK，失败返回MI_ERR
/////////////////////////////////////////////////////////////////////
#if 0
unsigned char Test_Communication(unsigned char cnt)
{
	unsigned char i,j;
 	 MF_NRST_H;
  	nfc_delay_us(200);
	for(i=0;( i<cnt && (j == 0x12 || j == 0x15) ) ;i++)
	{	
		nfc_delay_us(100);	
		j=ReadRawRC(0X37); 
	}
	if( j == 0x12 || j == 0x15 )
		return MI_OK;
	else
		return MI_ERR;
}
#endif

void Ws1850s_Init(void)
{
	PcdReset();
	// PcdAntennaOff();
	// PcdAntennaOn();
	// M500PcdConfigISOTypeA();
	pcd_lpcd_start(DELAT, SWINGSCNT);
}

/////////////////////////////////////////////////////////////////////
//功    能：复位芯片
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
void PcdReset(void)
{
	MF_NRST_H;
	nfc_delay_us(10);
	MF_NRST_L;
	nfc_delay_us(10);
	MF_NRST_H;
	nfc_delay_us(500);						//delay 500us 请客户确认delay_us函数延时准确。
	WriteRawRC(CommandReg, PCD_RESETPHASE); //软复位
	nfc_delay_us(2);
	WriteRawRC(ModeReg, 0x3D);				//和Mifare卡通讯，CRC初始值0x6363
	WriteRawRC(TReloadRegL, 30);			//重装定时器值高位
	WriteRawRC(TReloadRegH, 0);				//重装定时器值低位
	WriteRawRC(TModeReg, 0x8D);				//跟随协议启动和停止
	WriteRawRC(TPrescalerReg, 0x3E);		//6.78/3390,15ms产生中断
	WriteRawRC(TxASKReg, 0x40);				//
	// ClearBitMask(TestPinEnReg,0x80); //off MX and DTRQ out
}

/////////////////////////////////////////////////////////////////////
//开启天线
//每次启动或关闭天险发射之间应至少有1ms的间隔
/////////////////////////////////////////////////////////////////////
void PcdAntennaOn()
{
	WriteRawRC(TxControlReg, ReadRawRC(TxControlReg) | 0x03); //Tx1RFEn=1 Tx2RFEn=1
}

/////////////////////////////////////////////////////////////////////
//关闭天线
/////////////////////////////////////////////////////////////////////
void PcdAntennaOff(void)
{
	WriteRawRC(TxControlReg, ReadRawRC(TxControlReg) & (~0x03));
}

/**
 ****************************************************************
 * @brief pcd_config() 
 *
 * 配置芯片的A/B模式
 *
 * @param: uint8_t type   
 * @return: 
 * @retval: 
 ****************************************************************
 */

void PcdConfig(unsigned char type)
{
	MF_NRST_L;
	nfc_delay_us(100);
	MF_NRST_H;
	nfc_delay_us(100);
	PcdAntennaOff();
	//nfc_delay_us(500);

	if ('A' == type)
	{
		ClearBitMask(Status2Reg, BIT3);
		ClearBitMask(ComIEnReg, BIT7); // 高电平
		WriteRawRC(ModeReg, 0x3D);	   // 11 // CRC seed:6363
		WriteRawRC(RxSelReg, 0x86);	   //RxWait
		WriteRawRC(RFCfgReg, 0x58);	   //
		WriteRawRC(GsNReg, 0xf8);
		WriteRawRC(CWGsPReg, 0x3f);
		WriteRawRC(TxASKReg, 0x40);	 //15  //typeA
		WriteRawRC(TxModeReg, 0x00); //12 //Tx Framing A
		WriteRawRC(RxModeReg, 0x00); //13 //Rx framing A
		WriteRawRC(0x0C, 0x10);		 //^_^
		//兼容配置
		{
			unsigned char backup;
			backup = ReadRawRC(0x37);
			WriteRawRC(0x37, 0x00);
			{
				// 以下寄存器必须按顺序配置
				WriteRawRC(0x37, 0x5E);
				WriteRawRC(0x26, 0x48);
				WriteRawRC(0x17, 0x88);
				WriteRawRC(0x29, 0x12); //0x0F); //调制指数
				WriteRawRC(0x35, 0xED);
				WriteRawRC(0x3b, 0xA5);
				WriteRawRC(0x37, 0xAE);
				WriteRawRC(0x3b, 0x72);
			}
			WriteRawRC(0x37, backup);
		}
	}
	else if ('B' == type)
	{
		WriteRawRC(Status2Reg, 0x00);  //清MFCrypto1On
		ClearBitMask(ComIEnReg, BIT7); // 高电平触发中断
		WriteRawRC(ModeReg, 0x3F);	   // CRC seed:FFFF
		WriteRawRC(RxSelReg, 0x85);	   //RxWait
		WriteRawRC(RFCfgReg, 0x58);	   //
		//Tx
		WriteRawRC(GsNReg, 0xF8);	 //调制系数
		WriteRawRC(CWGsPReg, 0x3F);	 //
		WriteRawRC(ModGsPReg, 0x2F); //调制指数
		WriteRawRC(AutoTestReg, 0x00);
		WriteRawRC(TxASKReg, 0x00); // typeB
		WriteRawRC(TypeBReg, 0x13);
		WriteRawRC(TxModeReg, 0x83);	 //Tx Framing B
		WriteRawRC(RxModeReg, 0x83);	 //Rx framing B
		WriteRawRC(BitFramingReg, 0x00); //TxLastBits=0
		//兼容配置
		{
			unsigned char backup;
			backup = ReadRawRC(0x37);
			WriteRawRC(0x37, 0x00);
			{
				WriteRawRC(0x37, 0x5E);
				WriteRawRC(0x26, 0x48);
				WriteRawRC(0x17, 0x88);
				WriteRawRC(0x29, 0x12);
				WriteRawRC(0x35, 0xED);
				WriteRawRC(0x3b, 0xA5);
				WriteRawRC(0x37, 0xAE);
				WriteRawRC(0x3b, 0x72);
			}
			WriteRawRC(0x37, backup);
		}
	}
	else
	{
		// return USER_ERROR;
	}

	PcdAntennaOn();
	nfc_delay_us(100);
}

/////////////////////////////////////////////////////////////////////
//设置PCD定时器
//input:fwi=0~15
/////////////////////////////////////////////////////////////////////
void PcdSetTmo(unsigned char fwi)
{
	WriteRawRC(TPrescalerReg, (TP_FWT_302us)&0xFF);
	WriteRawRC(TModeReg, BIT7 | (((TP_FWT_302us) >> 8) & 0xFF));

	WriteRawRC(TReloadRegL, (1 << fwi) & 0xFF);
	WriteRawRC(TReloadRegH, ((1 << fwi) & 0xFF00) >> 8);
}

/////////////////////////////////////////////////////////////////////
//功    能：和ISO14443卡通讯
//参数说明：Command[IN]:命令字
//          pInData[IN]:发送到卡片的数据
//          InLenByte[IN]:发送数据的字节长度
//          pOutData[OUT]:接收到的卡片返回数据
//          *pOutLenBit[OUT]:返回数据的位长度
/////////////////////////////////////////////////////////////////////
unsigned char PcdComMF522(signed char Command,
						  unsigned char *pInData,
						  unsigned char InLenByte,
						  unsigned char *pOutData,
						  unsigned int *pOutLenBit)
{
	unsigned char recebyte = 0;
	unsigned char val;
	unsigned char err = 0;
	unsigned char irq_inv;
	unsigned char len_rest = 0;
	unsigned char len = 0;
	unsigned char status;
	unsigned char irqEn = 0x00;
	unsigned char waitFor = 0x00;
	unsigned char lastBits;
	uint16_t i;

	switch (Command)
	{
	case PCD_IDLE:
		irqEn = 0x00;
		waitFor = 0x00;
		break;

	case PCD_AUTHENT:
		irqEn = IdleIEn | TimerIEn;
		waitFor = IdleIRq;
		break;

	case PCD_RECEIVE:
		irqEn = RxIEn | IdleIEn;
		waitFor = RxIRq;
		recebyte = 1;
		break;

	case PCD_TRANSMIT:
		irqEn = TxIEn | IdleIEn;
		waitFor = TxIRq;
		break;

	case PCD_TRANSCEIVE:
		irqEn = RxIEn | IdleIEn | TimerIEn | TxIEn;
		waitFor = RxIRq;
		recebyte = 1;
		break;
	default:
		Command = MI_UNKNOWN_COMMAND;
		break;
	}

	if (Command != MI_UNKNOWN_COMMAND && (((Command == PCD_TRANSCEIVE || Command == PCD_TRANSMIT) && InLenByte > 0) || (Command != PCD_TRANSCEIVE && Command != PCD_TRANSMIT)))
	{
		WriteRawRC(CommandReg, PCD_IDLE);

		irq_inv = ReadRawRC(ComIEnReg) & BIT7;
		WriteRawRC(ComIEnReg, irq_inv | irqEn | BIT0); //使能Timer 定时器中断
		WriteRawRC(ComIrqReg, 0x7F);				   //Clear INT
		WriteRawRC(DivIrqReg, 0x7F);				   //Clear INT
		//Flush Fifo
		SetBitMask(FIFOLevelReg, BIT7);
		if (Command == PCD_TRANSCEIVE || Command == PCD_TRANSMIT || Command == PCD_AUTHENT)
		{
			len_rest = InLenByte;
			if (len_rest >= FIFO_SIZE)
			{
				len = FIFO_SIZE;
			}
			else
			{
				len = len_rest;
			}

			for (i = 0; i < len; i++)
			{
				WriteRawRC(FIFODataReg, pInData[i]);
			}

			len_rest -= len; //Rest bytes

			if (len_rest != 0)
			{
				WriteRawRC(ComIrqReg, BIT2); // clear LoAlertIRq
				SetBitMask(ComIEnReg, BIT2); // enable LoAlertIRq
			}

			WriteRawRC(CommandReg, Command);
			if (Command == PCD_TRANSCEIVE)
			{
				SetBitMask(BitFramingReg, 0x80);
			}

			while (len_rest != 0)
			{
				nfc_delay_ms(2);
				if (len_rest > (FIFO_SIZE - WATER_LEVEL))
				{
					len = FIFO_SIZE - WATER_LEVEL;
				}
				else
				{
					len = len_rest;
				}
				for (i = 0; i < len; i++)
				{
					WriteRawRC(FIFODataReg, pInData[InLenByte - len_rest + i]);
				}

				WriteRawRC(ComIrqReg, BIT2); //在write fifo之后，再清除中断标记才可以
				len_rest -= len;			 //Rest bytes
				if (len_rest == 0)
				{
					ClearBitMask(ComIEnReg, BIT2); // disable LoAlertIRq
				}
			}
			//Wait TxIRq
			nfc_delay_ms(2);
			//while (INT_PIN == 0);
			val = ReadRawRC(ComIrqReg);
			if (val & TxIRq)
			{
				WriteRawRC(ComIrqReg, TxIRq);
			}
		}

		if (PCD_RECEIVE == Command)
		{
			SetBitMask(ControlReg, BIT6); // TStartNow
		}

		len_rest = 0;				 // bytes received
		WriteRawRC(ComIrqReg, BIT3); // clear HoAlertIRq
		SetBitMask(ComIEnReg, BIT3); // enable HoAlertIRq

		nfc_delay_ms(2);

		while (1)
		{
			nfc_delay_ms(2);
			val = ReadRawRC(ComIrqReg);
			if ((val & BIT3) && !(val & BIT5))
			{
				if (len_rest + FIFO_SIZE - WATER_LEVEL > 255)
				{
					break;
				}
				for (i = 0; i < FIFO_SIZE - WATER_LEVEL; i++)
				{
					pOutData[len_rest + i] = ReadRawRC(FIFODataReg);
				}
				WriteRawRC(ComIrqReg, BIT3); //在read fifo之后，再清除中断标记才可以
				len_rest += FIFO_SIZE - WATER_LEVEL;
			}
			else
			{
				ClearBitMask(ComIEnReg, BIT3); //disable HoAlertIRq
				break;
			}
		}

		val = ReadRawRC(ComIrqReg);

		WriteRawRC(ComIrqReg, val); // 清中断

		if (val & BIT0)
		{ //发生超时
			status = MI_NOTAGERR;
		}
		else
		{
			err = ReadRawRC(ErrorReg);

			status = MI_COM_ERR;
			if ((val & waitFor) && (val & irqEn))
			{
				if (!(val & ErrIRq))
				{ //指令执行正确
					status = MI_OK;

					if (recebyte)
					{
						val = 0x7F & ReadRawRC(FIFOLevelReg);
						lastBits = ReadRawRC(ControlReg) & 0x07;
						if (len_rest + val > MAX_TRX_BUF_SIZE)
						{ //长度过长超出缓存
							status = MI_COM_ERR;
						}
						else
						{
							if (lastBits && val) //防止spi读错后 val-1成为负值
							{
								*pOutLenBit = (val - 1) * 8 + lastBits;
							}
							else
							{
								*pOutLenBit = val * 8;
							}
							*pOutLenBit += len_rest * 8;

							if (val == 0)
							{
								val = 1;
							}
							for (i = 0; i < val; i++)
							{
								pOutData[len_rest + i] = ReadRawRC(FIFODataReg);
							}
						}
					}
				}
				else if ((err & CollErr) && (!(ReadRawRC(CollReg) & BIT5)))
				{ //a bit-collision is detected
					status = MI_COLLERR;
					if (recebyte)
					{
						val = 0x7F & ReadRawRC(FIFOLevelReg);
						lastBits = ReadRawRC(ControlReg) & 0x07;
						if (len_rest + val > MAX_TRX_BUF_SIZE)
						{ //长度过长超出缓存
							;
						}
						else
						{
							if (lastBits && val) //防止spi读错后 val-1成为负值
							{
								*pOutLenBit = (val - 1) * 8 + lastBits;
							}
							else
							{
								*pOutLenBit = val * 8;
							}
							*pOutLenBit += len_rest * 8;
							if (val == 0)
							{
								val = 1;
							}
							for (i = 0; i < val; i++)
							{
								pOutData[len_rest + i + 1] = ReadRawRC(FIFODataReg);
							}
						}
					}
					pOutData[0] = (ReadRawRC(CollReg) & CollPos);
					if (pOutData[0] == 0)
					{
						pOutData[0] = 32;
					}

					pOutData[0]--; // 与之前版本有点映射区别，为了不改变上层代码，这里直接减一；
				}
				else if ((err & CollErr) && (ReadRawRC(CollReg) & BIT5))
				{
					;
				}
				//else if (err & (CrcErr | ParityErr | ProtocolErr))
				else if (err & (ProtocolErr))
				{
					status = MI_FRAMINGERR;
				}
				else if ((err & (CrcErr | ParityErr)) && !(err & ProtocolErr))
				{
					//EMV  parity err EMV 307.2.3.4
					val = 0x7F & ReadRawRC(FIFOLevelReg);
					lastBits = ReadRawRC(ControlReg) & 0x07;
					if (len_rest + val > MAX_TRX_BUF_SIZE)
					{ //长度过长超出缓存
						status = MI_COM_ERR;
					}
					else
					{
						if (lastBits && val)
						{
							*pOutLenBit = (val - 1) * 8 + lastBits;
						}
						else
						{
							*pOutLenBit = val * 8;
						}
						*pOutLenBit += len_rest * 8;
					}
					status = MI_INTEGRITY_ERR;
				}
				else
				{
					status = MI_INTEGRITY_ERR;
				}
			}
			else
			{
				status = MI_COM_ERR;
			}
		}
		SetBitMask(ControlReg, BIT7);  // TStopNow =1,必要的；
		WriteRawRC(ComIrqReg, 0x7F);   // 清中断0
		WriteRawRC(DivIrqReg, 0x7F);   // 清中断1
		ClearBitMask(ComIEnReg, 0x7F); //清中断使能,最高位是控制位
		ClearBitMask(DivIEnReg, 0x7F); //清中断使能,最高位是控制位
		WriteRawRC(CommandReg, PCD_IDLE);
	}
	else
	{
		status = USER_ERROR;
	}
	return status;
}

///////////////////////////////////////////////////////////////////////
////功    能：读A卡，并返回卡号
//  参    数：uid  寻感应区内所有符合14443A标准的卡(0x52)/
//								  寻未进入休眠状态的卡(0x26)
///////////////////////////////////////////////////////////////////////
unsigned char ComReqA_UID(unsigned char *uid)
{
	//uint8_t bufCard[64];
	//unsigned char cmdb[2];
	unsigned char i;
	unsigned char len;
	uint8_t *pType;
	PcdConfig('A');
	nfc_delay_ms(1);
	//cmdb[1] = 0x52;
	nfc_delay_ms(1);

	if (PcdRequest(PICC_REQALL, CT) != MI_OK)
		return MI_ERR;
	if (PcdAnticoll(IDA, &len) != MI_OK) //一次防冲突及选卡
		return MI_ERR;
	for (i = 0; i < 4; i++)
	{
		uid[i] = IDA[i];
	}
	if (PcdSelect(IDA, pType) != MI_OK)
		return MI_ERR;
	return MI_OK;
}

unsigned char ComReqA_Block(unsigned char rw, unsigned char Block)
{
	unsigned char status;
	if (PcdAuthState(PICC_AUTHENT1A, Block, PassWd, IDA) != MI_OK)
		return MI_ERR;
	switch (rw)
	{
	case 0:
		status = PcdRead(Block, RWDATA);
		break;
	case 1:
		status = PcdWrite(Block, RWDATA);
		break;
	default:
		break;
	}

	return status;
}

unsigned char ComReqA(unsigned char rw, unsigned char Block, unsigned char *pType)
{
	unsigned char status = MI_OK;
	unsigned char len;
	PcdConfig('A');
	if (PcdRequest(PICC_REQALL, CT) != MI_OK) //寻卡
		return MI_ERR;
	//if(PcdFastSearchCard()!=MI_OK)
	if (PcdAnticoll(IDA, &len) != MI_OK) //一次防冲突
		return MI_ERR;

	if (PcdSelect(IDA, pType) != MI_OK)
		return MI_ERR;
#if 0 //操作扇区
	if(PcdSelect(IDA)!=MI_OK)//选卡
			return MI_ERR;
	if(PcdAuthState(PICC_AUTHENT1A,Block,PassWd,IDA)!=MI_OK)//校验密钥
			return MI_ERR;
	switch(rw)
	{
		case 0: status = PcdRead(Block,RWDATA);break;//读数据块
		case 1: status = PcdWrite(Block,RWDATA);break;	//写数据块
		default: break;
	}
#endif
	return status;
}
///////////////////////////////////////////////////////////////////////
////功    能：读B卡，并返回卡号
//  参    数：pcmd  寻感应区内所有符合14443b标准的卡(0x08)/
///////////////////////////////////////////////////////////////////////
unsigned char ComReqB(void)
{

	uint8_t status = MI_ERR;
	uint8_t i;
	uint8_t cnt;
	uint8_t ATQB[16];

	PcdConfig('B');

	cnt = 3; //应用中 可以使用轮询N次
	while (cnt--)
	{
		status = PcdRequestB(0x08, 0, 0, ATQB);

		if (status == MI_COLLERR) // 有冲突，超过一张卡
		{
			if ((status = PcdRequestB(0x08, 0, 2, ATQB)) != MI_OK)
			{
				for (i = 1; i < 4; i++)
				{
					if ((status = PcdSlotMarker(i, ATQB)) == MI_OK)
					{
						break;
					}
				}
				if (status == MI_OK)
				{
					break;
				}
			}
			else
			{
				break;
			}
		}
	}

	if (status == MI_OK)
	{
		//typeB 106默认速率
		status = PcdAttriB(&ATQB[1], 0, ATQB[10] & 0x0f, PICC_CID, ATQB);

		if (status == MI_OK)
		{
			ATQB[0] = 0x50;	   //恢复默认值
			GetIdcardNum(IDB); //获取卡号
		}
	}

	return status;
}

/////////////////////////////////////////////////////////////////////
//功    能：寻卡
//参数说明: req_code[IN]:寻卡方式
//                0x52 = 寻感应区内所有符合14443A标准的卡
//                0x26 = 寻未进入休眠状态的卡
//          pTagType[OUT]：卡片类型代码
//                0x4400 = Mifare_UltraLight
//                0x0400 = Mifare_One(S50)
//                0x0200 = Mifare_One(S70)
//                0x0800 = Mifare_Pro(X)
//                0x4403 = Mifare_DESFire
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
unsigned char PcdRequest(unsigned char req_code, unsigned char *pTagType)
{
	unsigned char status;
	unsigned char i;
	unsigned int unLen;
	unsigned char ucComMF522Buf[MAXRLEN];
	status = MI_OK;
	ClearBitMask(Status2Reg, 0x08);
	WriteRawRC(BitFramingReg, 0x07);
	SetBitMask(TxControlReg, 0x03);
	i = ReadRawRC(0X37);
	if (i == 0x12 || i == 0x15)
	{
		nfc_delay_ms(2);
	}

	ucComMF522Buf[0] = req_code;

	status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 1, ucComMF522Buf, &unLen);
	//   UART_send_byte(status);
	if ((status == MI_OK) && (unLen == 0x10))
	{
		*pTagType = ucComMF522Buf[0];
		*(pTagType + 1) = ucComMF522Buf[1];
	}
	else
	{
		status = MI_ERR;
	}

	return status;
}
/////////////////////////////////////////////////////////////////////
//功    能：A卡快速寻卡函数
//说明: 可在短时间内寻卡，最快打开天线600us可寻到A卡
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
unsigned char PcdFastSearchCard(void)
{
	unsigned char irqEn = 0x77;
	unsigned char errmask = 0x30;
	unsigned char errflag;
	unsigned int times;
	MF_NRST_H;
	nfc_delay_us(10);
	MF_NRST_L; //
	nfc_delay_us(10);
	MF_NRST_H;
	nfc_delay_us(500); //delay 500us
	ClearBitMask(TestPinEnReg, 0x9E);
	WriteRawRC(ModeReg, 0x3D);		 //和Mifare卡通讯，CRC初始值0x6363
	WriteRawRC(TxASKReg, 0x40);		 //100%ASK调制
	WriteRawRC(BitFramingReg, 0x07); //
	//WriteRawRC(TxControlReg,0x83); //T1，T2发送经过连续调制的载波。出现载波0X83
	//nfc_delay_us(500);
	WriteRawRC(GsNReg, 0xf8);
	WriteRawRC(CWGsPReg, 0x3f);
	WriteRawRC(ComIEnReg, irqEn | 0x80); //
	WriteRawRC(ComIrqReg, 0x14);		 //
	WriteRawRC(CommandReg, PCD_IDLE);	 //
	WriteRawRC(FIFOLevelReg, 0x80);		 //
	WriteRawRC(TxControlReg, 0x83);		 //T1，T2发送经过连续调制的载波。出现载波0X83
	// nfc_delay_us(100);					 // delay(7500);

	WriteRawRC(FIFODataReg, PICC_REQIDL);	//先将数据写入fifo  0X26
	WriteRawRC(CommandReg, PCD_TRANSCEIVE); //执行操作命令写入卡中
	WriteRawRC(BitFramingReg, 0x87);		//启动数据发送
	// nfc_delay_us(100);						// delay(7500);
	times = 25;
	do
	{
		errflag = ReadRawRC(ComIrqReg); //判断是否有中断发生
		times--;
	} while ((times != 0) && !(errflag & errmask));
	if (times == 0)
	{
#if 1
		MF_NRST_L; //硬复位
#else
		//  WriteRawRC(TxControlReg,0x80); //软复位
#endif
		return MI_ERR;
	}

	return MI_OK;
}

/////////////////////////////////////////////////////////////////////
//功    能：防冲撞
//参数说明: pSnr[OUT]:卡片序列号，4字节
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
unsigned char PcdAnticoll(unsigned char *pSnr, unsigned char *pLen)
{
	unsigned char status;
	unsigned char i, snr_check = 0;
	unsigned int unLen;
	unsigned char ucComMF522Buf[MAXRLEN];

	ClearBitMask(Status2Reg, 0x08);
	WriteRawRC(BitFramingReg, 0x00);
	ClearBitMask(CollReg, 0x80);

	ucComMF522Buf[0] = PICC_ANTICOLL1;
	ucComMF522Buf[1] = 0x20;

	status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 2, ucComMF522Buf, &unLen);

	if (status == MI_OK)
	{
		for (i = 0; i < 4; i++)
		{
			*(pSnr + i) = ucComMF522Buf[i];
			snr_check ^= ucComMF522Buf[i];
		}
		if (snr_check != ucComMF522Buf[i])
		{
			status = MI_ERR;
		}
		else
		{
			*pLen = 4;
		}
	}

	SetBitMask(CollReg, 0x80);
	return status;
}

/////////////////////////////////////////////////////////////////////
//功    能：选定卡片
//参数说明: pSnr[IN]:卡片序列号，4字节
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
unsigned char PcdSelect(unsigned char *pSnr, uint8_t *pType)
{
	unsigned char status;
	unsigned char i;
	unsigned int unLen;
	unsigned char ucComMF522Buf[MAXRLEN];

	ucComMF522Buf[0] = PICC_ANTICOLL1;
	ucComMF522Buf[1] = 0x70;
	ucComMF522Buf[6] = 0;
	for (i = 0; i < 4; i++)
	{
		ucComMF522Buf[i + 2] = *(pSnr + i);
		ucComMF522Buf[6] ^= *(pSnr + i);
	}
	CalulateCRC(ucComMF522Buf, 7, &ucComMF522Buf[7]);

	ClearBitMask(Status2Reg, 0x08);

	status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 9, ucComMF522Buf, &unLen);

	if ((status == MI_OK) && (unLen == 0x18))
	{
		*pType = 0;
		*pType = ucComMF522Buf[0];
		//printf("*pType %x ucComMF522Buf[0]%x\n",*pType,ucComMF522Buf[0]);
		status = MI_OK;
	}
	else
	{
		status = MI_ERR;
	}

	return status;
}

/////////////////////////////////////////////////////////////////////
//功    能：验证卡片密码
//参数说明: auth_mode[IN]: 密码验证模式
//                 0x60 = 验证A密钥
//                 0x61 = 验证B密钥
//          addr[IN]：块地址
//          pKey[IN]：密码
//          pSnr[IN]：卡片序列号，4字节
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
unsigned char PcdAuthState(unsigned char auth_mode, unsigned char addr, unsigned char *pKey, unsigned char *pSnr)
{
	unsigned char status;
	unsigned int unLen;
	unsigned char i, ucComMF522Buf[MAXRLEN];

	ucComMF522Buf[0] = auth_mode;
	ucComMF522Buf[1] = addr;
	for (i = 0; i < 6; i++)
	{
		ucComMF522Buf[i + 2] = *(pKey + i);
	}
	for (i = 0; i < 6; i++)
	{
		ucComMF522Buf[i + 8] = *(pSnr + i);
	}

	status = PcdComMF522(PCD_AUTHENT, ucComMF522Buf, 12, ucComMF522Buf, &unLen);
	if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))
	{
		status = MI_ERR;
	}

	return status;
}

/////////////////////////////////////////////////////////////////////
//功    能：读取M1卡一块数据
//参数说明: addr[IN]：块地址
//          p [OUT]：读出的数据，16字节
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
unsigned char PcdRead(unsigned char addr, unsigned char *pData)
{
	uint8_t status;
	unsigned int unLen;
	unsigned char i, ucComMF522Buf[MAXRLEN];

	ucComMF522Buf[0] = PICC_READ;
	ucComMF522Buf[1] = addr;
	CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);

	status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);
	if ((status == MI_OK) && (unLen == 0x90))
	{
		for (i = 0; i < 16; i++)
		{
			*(pData + i) = ucComMF522Buf[i];
		}
	}
	else
	{
		status = MI_ERR;
	}

	return status;
}

/////////////////////////////////////////////////////////////////////
//功    能：写数据到M1卡一块
//参数说明: addr[IN]：块地址
//          p [IN]：写入的数据，16字节
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
unsigned char PcdWrite(unsigned char addr, unsigned char *pData)
{
	unsigned char status;
	unsigned int unLen;
	unsigned char i, ucComMF522Buf[MAXRLEN];

	ucComMF522Buf[0] = PICC_WRITE;
	ucComMF522Buf[1] = addr;
	CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);

	status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);

	if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
	{
		status = MI_ERR;
	}

	if (status == MI_OK)
	{
		for (i = 0; i < 16; i++)
		{
			ucComMF522Buf[i] = *(pData + i);
		}
		CalulateCRC(ucComMF522Buf, 16, &ucComMF522Buf[16]);

		status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 18, ucComMF522Buf, &unLen);
		if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
		{
			status = MI_ERR;
		}
	}

	return status;
}

/////////////////////////////////////////////////////////////////////
//用MF522计算CRC16函数
/////////////////////////////////////////////////////////////////////
void CalulateCRC(unsigned char *pIndata, unsigned char len, unsigned char *pOutData)
{
	unsigned char i, n;
	ClearBitMask(DivIrqReg, 0x04);
	WriteRawRC(CommandReg, PCD_IDLE);
	SetBitMask(FIFOLevelReg, 0x80);
	for (i = 0; i < len; i++)
	{
		WriteRawRC(FIFODataReg, *(pIndata + i));
	}
	WriteRawRC(CommandReg, PCD_CALCCRC);
	i = 0xFF;
	do
	{
		n = ReadRawRC(DivIrqReg);
		i--;
	} while ((i != 0) && !(n & 0x04));
	pOutData[0] = ReadRawRC(CRCResultRegL);
	pOutData[1] = ReadRawRC(CRCResultRegM);
}

void M500PcdConfigISOTypeA(void) //ISO14443_A//A:NXP,B:MOTO
{
	ClearBitMask(Status2Reg, 0x08); //清除寄存器-接收器，发送器和数据模式检测器的状态标志
	WriteRawRC(ModeReg, 0x3D);		//3F 选择模式-定义发送和接受的常用模式
	WriteRawRC(RxSelReg, 0x86);		//84  内部接收设置
	WriteRawRC(RFCfgReg, 0x7F);		//4F  配置接收器增益

	WriteRawRC(TReloadRegL, 30); //tmoLength);// TReloadVal = 'h6a =tmoLength(dec)
	WriteRawRC(TReloadRegH, 0);		//16位长的定时器重装值
	WriteRawRC(TModeReg, 0x8D);		//定义内部定时器的设置
	WriteRawRC(TPrescalerReg, 0x3E);

	//nfc_delay_us(400);
	//PcdAntennaOn();
}

void pcd_lpcd_start(unsigned char delta, unsigned char swingscnt)
{
	unsigned int sw;
	sw = swingscnt;
	delta = 0X30 + delta;

	WriteRawRC(0x01, 0x0F);		 //软复位nfc芯片，清寄存器
	WriteRawRC(0x14, 0x23);		 //Tx2CW = 1 ,continue?????? 打开TX1 TX2
	WriteRawRC(0x37, 0x5e);		 //寄存器操作使能
	WriteRawRC(0x3c, delta);	 //Delta[3:0]
	WriteRawRC(0x3d, 0x0D);		 //休眠时间	  //LPCD休眠时间  0x20为100ms
	WriteRawRC(0x3e, 0x90 | sw); //探测时间  0x90：SKIP 消抖一次，
	WriteRawRC(0x37, 0x00);		 //关闭私有寄存器保护开关

	WriteRawRC(0x37, 0x5a); //打开私有寄存器保护开关
#if 1
	WriteRawRC(0x38, 0x50); //设置LPCD 发射功率 高四位
	WriteRawRC(0x39, 0x10); //设置LPCD 发射功率 低六位
	//WriteRawRC(0x31, 0xA1);//设置LPCD 检测参考值
#else
	WriteRawRC(0x38, 0x70);//设置LPCD 发射功率 高四位
	WriteRawRC(0x39, 0x1f);//设置LPCD 发射功率 低六位
#endif
	WriteRawRC(0x33, 0x60); //调整步长,20,60,A0,E0 值越小，步长越长，影响38 39 3e 3c寄存器参数
	WriteRawRC(0x36, 0x80);
	WriteRawRC(0x37, 0x00); //关闭私有寄存器保护开关

	//ClearBitMask(0x02, 0x80); //配置IRQ为高电平中断
	SetBitMask(0x02, 0x80); //配置IRQ为低电平中断
	//WriteRawRC(0x03, 0xA0);	//打开卡探测中断,IRQ 为CMOS 输出
	WriteRawRC(0X03, 0XA0); //IRQ????	使能上拉
	WriteRawRC(0x01, 0x10); //PCD soft powerdown
	printf("lpcd start\r\n");
	
#if 0		//调试的用
	nfc_delay_ms(200);
	WriteRawRC(0x37, 0x5a); //打开私有寄存器保护开关
	printf("31:%d\r\n",ReadRawRC(0x31));
	printf("36:%d\r\n",ReadRawRC(0x36));
	WriteRawRC(0x37, 0x00);		 //关闭私有寄存器保护开关
#endif
}

//******WS1850结束LPCD模式*******************
void pcd_lpcd_end(void)
{
	WriteRawRC(0x01, 0x0F); //?????????lpcd
	printf("lpcd end\r\n");
}

//****检测卡片类型以及卡片的信息******************************
unsigned int Card_Check(unsigned char *id, unsigned int len, unsigned char *pType)
{
	//unsigned char i;
	unsigned char status = MI_OK;
	unsigned char Block = 0x05;
	status = ComReqA(READ, Block, pType);
	if (status == MI_OK)
	{
		// for(i=0;i<4;i++)
		// {
		// 	printf("IDA[%d]=%x\n", i, IDA[i]);
		// }

		if (id && len >= 4)
		{
			memcpy(id, IDA, 4);
			return 4;
		}
	}

	return 0;

#if 0
	status = ComReqB();
	if(status ==MI_OK)
	{
		for(i=0;i<8;i++)
		{ 
			LOG_INFO("IDA[%d]=%x\n", i, IDB[i]);   
		}
		card_notify_vtask(CARD_TYPE_B, IDB, 8);
		return;
	}
#endif
}

//lpcd 唤醒后的读卡应用函数
void pcd_lpcd_application(void)
{
	unsigned char id[10];
    unsigned char type;
	if((ReadRawRC(DivIrqReg) & 0x20))
	{
		WriteRawRC(DivIrqReg, 0x20); //
		pcd_lpcd_end(); //end LPCD       			
		Card_Check(id, sizeof(id), &type);																		
		MF_NRST_L;
		nfc_delay_ms(200); //读卡结束后等待卡片离开	
	}
	MF_NRST_L;
	nfc_delay_us(500);
	MF_NRST_H;
	nfc_delay_us(500);	
}

/* 2021.04.07 add*/

/**
 * @brief MF5221通用接口
 * 
 * @param Command 
 * @param pDataIn 
 * @param InLenByte 
 * @param pDataOut 
 * @param pOutLenBit 
 * @return unsigned char 
 */
unsigned char PcdComMF5221(uint8_t Command, uint8_t *pDataIn, uint8_t InLenByte, uint8_t *pDataOut, uint16_t *pOutLenBit)
{
	unsigned char status = MI_ERR;
	uint8_t irqEn = 0x00;
	uint8_t waitFor = 0x00;
	uint8_t lastBits;
	uint8_t n;
	uint32_t i;
	n = ReadRawRC(ComIrqReg); //读取中断标志,检查数据返回
	// printf("^^^^^^^^^^^^^^^^^^^^n= %x\n",n);
	switch (Command)
	{
	case PCD_AUTHENT:
		irqEn = 0x12;
		waitFor = 0x10;
		break;
	case PCD_TRANSCEIVE:
		irqEn = 0x77;
		waitFor = 0x30; // 接受到数据及命令执行完毕
		break;
	default:
		break;
	}
	WriteRawRC(ComIEnReg, irqEn | 0x80); // 容许除定时器中断请求以为得所有中断请求
	ClearBitMask(ComIrqReg, 0x80);		 // 屏蔽位清除
	WriteRawRC(CommandReg, PCD_IDLE);	 // 取消当前命令
	SetBitMask(FIFOLevelReg, 0x80);		 // 清除FIFO中的读写指针

	for (i = 0; i < InLenByte; i++)
	{
		WriteRawRC(FIFODataReg, pDataIn[i]); //数据写入FIFO
	}
	WriteRawRC(CommandReg, Command); //写入命令,将缓冲区中的数据发送到天线,并激活自动接收器

	if (Command == PCD_TRANSCEIVE) //如果命令为0C
	{
		SetBitMask(BitFramingReg, 0x80); //相当于启动发送STARTSENG
	}
	i = 10000; //根据时钟频率调整，操作M1卡最大等待时间=600,操作CPU卡最大等待时间=1200
	do
	{
		n = ReadRawRC(ComIrqReg); //读取中断标志,检查数据返回
		i--;

	} while ((i != 0) && !(n & 0x20) && !(n & waitFor)); // 定时器未超时,没有错误,0x01,0x30
	ClearBitMask(BitFramingReg, 0x80);					 // 相当于清除发送STARTSENG
	// printf("n= %x\n", n);
	// printf("i= %d\n", i);
	if (i != 0)											 // 定时时间到，i，没有递减到0
	{
		// printf("====================i != 0\n");
		if (!(ReadRawRC(ErrorReg) & 0x1B)) // 判断有无出现错误标志	 Buffer溢出,位冲突,接收CRC错误,奇偶校验错误,
		{
			// printf("!(ReadRawRC(ErrorReg) & 0x1B\n");
			status = MI_OK;		  // 初始化状态
			if (n & irqEn & 0x01) // 若是PCD_TRANSCEIVE, irq = 0x77,  定时器为0中断产生,定时器为0时为错误
			{
				//status = MI_NOTAGERR; // 搜索不到卡
				//printf("NO CARD\n");
			}
			if (Command == PCD_TRANSCEIVE) // 如果是发送接收指令
			{
				n = ReadRawRC(FIFOLevelReg); // 读取接收到的数据的字节数
				//printf("ReadRawRC(FIFOLevelReg); %x\n",n);
				lastBits = ReadRawRC(ControlReg) & 0x07; // 2-0:RxLastBits,显示接收到最后一个字节的位数
				if (lastBits)							 // 若该位为0，最后整个字节有效
				{
					*pOutLenBit = (n - 1) * 8 + lastBits; //pOutLenBit记录总共收到的位数
				}
				else
				{
					*pOutLenBit = n * 8; //接收完整位数
				}
				if (n == 0) //假如没有中断产生
				{
					n = 1; //n置1
				}
				if (n > 64) // 一次最大能接受到的字节数
				{
					n = 64; //超出最大长度,只接受最大长度的值
				}
				for (i = 0; i < n; i++)
				{
					pDataOut[i] = ReadRawRC(FIFODataReg); //从FIFO读取数据
				}
			}
		}
		else
		{
			//printf("status = MI_ERR; !!!!!!!!!!!!!!!!!!!!\n");
			status = MI_ERR; //有错误
		}
	}
	//printf("#################################\n");
	SetBitMask(ControlReg, 0x80);	  //停止定时器
	WriteRawRC(CommandReg, PCD_IDLE); //清空指令

	if ((status == MI_OK) && (*pOutLenBit == 0))
	{
		printf("######PcdComMF5221 proceess error\r\n");
	}

	return status; //返回状态
}

/**
 * @brief 获取Rats CPU复位
 * 
 * @param DataOut 
 * @param Len 
 * @return unsigned char 
 */
unsigned char PcdRats(uint8_t *DataOut, uint8_t *Len)
{
	unsigned char status = MI_ERR;
	uint16_t unLen;
	uint8_t ucComMF522Buf[64];
	//uint8_t i = 0;
	ClearBitMask(Status2Reg, 0x08); // 清空校验成功标志,清除MFCrypto1On位

	memset(ucComMF522Buf, 0x00, 64);

	ucComMF522Buf[0] = 0xE0;
	ucComMF522Buf[1] = 0x51;

	CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]); // 生成发送内容的CRC校验,保存到最后两个字节

	status = PcdComMF5221(PCD_TRANSCEIVE, ucComMF522Buf, 4, DataOut, &unLen); // 将收到的卡片类型号保存
	// printf("PcdRats send:\n");
	// for(i = 0;i < 64 ;i++)
	// {
	//     printf("%x",ucComMF522Buf[i]);
	// }
	// printf("\n");
	// printf("PcdRats recv:\n");
	// for(i = 0;i < 64 ;i++)
	// {
	//     printf("%x",DataOut[i]);
	// }
	// printf("\n");
	if (status == MI_OK)
	{
		Len[0] = unLen / 8;
		status = MI_OK;
	}
	else
	{
		status = MI_ERR;
	}

	// LOG_INFO("PcdRats status=%d num=%d\n", status, Len[0]);
	return status; //返回结果
}

/**
 * @brief 通用APDU接口
 * 
 * @param pDataIn 
 * @param In_Len 
 * @param pDataOut 
 * @param Out_Len 
 * @return unsigned char 
 */
unsigned char ComReqCpu(uint8_t *pDataIn, uint8_t In_Len, uint8_t *pDataOut, uint8_t *Out_Len)
{
	unsigned char status = MI_ERR;
	uint8_t ucComMF522Buf[64];
	static uint8_t Pcb = 0x00;
	uint16_t unLen;
	uint8_t i;

	//ClearBitMask(RxModeReg, BIT7); // 不使能接收CRC
	ClearBitMask(Status2Reg, 0x08); // 清空校验成功标志,清除MFCrypto1On位
	memset(ucComMF522Buf, 0x00, 64);

	switch (Pcb)
	{
	case 0x00:
		Pcb = 0x0A;
		break;
	case 0x0A:
		Pcb = 0x0B;
		break;
	case 0x0B:
		Pcb = 0x0A;
		break;
	default:
		Pcb = 0x0A;
		break;
	}

	if (pDataIn[1] == 0xA4)
		Pcb = 0x0A;

	ucComMF522Buf[0] = Pcb;
	ucComMF522Buf[1] = 0x01;

	for (i = 0; i < In_Len; i++)
	{
		ucComMF522Buf[2 + i] = pDataIn[i];
	}

	CalulateCRC(ucComMF522Buf, In_Len + 2, &ucComMF522Buf[In_Len + 2]); // 生成发送内容的CRC校验,保存到最后两个字节

	status = PcdComMF5221(PCD_TRANSCEIVE, ucComMF522Buf, In_Len + 4, pDataOut, &unLen);

	if (status == MI_OK)
	{
		Out_Len[0] = unLen / 8 - 2; //去掉后面的两字节crc校验
		status = MI_OK;
	}
	else
	{
		status = MI_ERR;
	}

	// LOG_INFO("ComReqCpu status=%d num=%d Pcb=0x%x\n", status, Out_Len[0], Pcb);
	return status;
}
